package com.example.cheeseerpadmin.sys.controller;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.cheeseerpadmin.sys.common.*;
import com.example.cheeseerpadmin.sys.entity.SysDept;
import com.example.cheeseerpadmin.sys.entity.SysRole;
import com.example.cheeseerpadmin.sys.entity.SysUser;
import com.example.cheeseerpadmin.sys.service.SysDeptService;
import com.example.cheeseerpadmin.sys.service.SysRoleService;
import com.example.cheeseerpadmin.sys.service.SysUserService;
import com.example.cheeseerpadmin.sys.vo.UserVo;
import org.apache.catalina.User;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    public SysUserService sysUserService;
    @Autowired
    public SysDeptService sysDeptService;
    @Autowired
    public SysRoleService sysRoleService;

    /**
     * 加载用户的全部数据以及进行模糊查询
     * 这里使用or()进行连接查询时需要放到最前面
     * page.getRecords得到的就是一个list集合，我们可以对这个集合进行操作，例如对直属领导和所属部门进行赋值
     *
     * @param userVo
     * @return
     */
    @RequestMapping("/loadAllUser")
    public DataGridView loadAllUser(UserVo userVo) {
        Page<SysUser> userVoPage = new Page<>(userVo.getPage(), userVo.getLimit());
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(userVo.getLoginname()), "loginname", userVo.getLoginname())
                .or().eq(StringUtils.isNotBlank(userVo.getName()), "name", userVo.getName());
        queryWrapper.eq(StringUtils.isNotBlank(userVo.getAddress()), "address", userVo.getAddress());
        queryWrapper.ge(userVo.getStartDate() != null, "hiredate", userVo.getStartDate());
        queryWrapper.le(userVo.getEndDate() != null, "hiredate", userVo.getEndDate());
        queryWrapper.eq("type", Constant.USER_TYPE_NORMAL);//查询系统用户，对于type为0的用户，我们是不支持查找的
        queryWrapper.eq(userVo.getDeptid() != null, "deptid", userVo.getDeptid());
        Page<SysUser> page = sysUserService.page(userVoPage, queryWrapper);
        List<SysUser> records = page.getRecords();

        //在使用了缓存切面的方法时，我们首先要对其参数做是否为null判断，不然就会爆出一个nullPointerException
        for (SysUser sysUser : records) {
            Integer deptid = sysUser.getDeptid();
            if (deptid != null) {
                SysDept sysDept = sysDeptService.getById(deptid);
                sysUser.setDeptname(sysDept.getTitle());
            }
            Integer mgr = sysUser.getMgr();
            if (mgr != null) {
                SysUser user = sysUserService.getById(mgr);
                sysUser.setLeadername(user.getName());
            }
        }
        return new DataGridView(page.getTotal(), records);
    }

    /**
     * 加载查询条件当中所属部门用到的下拉树的list格式数据
     *
     * @return
     */
    @RequestMapping("/loadDeptTreeJson")
    public DataGridView loadDeptTreeJson() {
        List<SysDept> list = sysDeptService.list();
        List<TreeNode> treeNodes = new ArrayList<>();
        for (SysDept sysDept : list) {
            TreeNode treeNode = new TreeNode(sysDept.getId(), sysDept.getPid(), sysDept.getTitle(), sysDept.getOpen() == 1);
            treeNodes.add(treeNode);
        }
        return new DataGridView(treeNodes);
    }

    /**
     * 添加用户
     *
     * @param userVo
     * @return
     */
    @RequestMapping("/addUser")
    public ResultObj addUser(UserVo userVo) {
        try {
            userVo.setHiredate(new Date());
            userVo.setType(Constant.USER_TYPE_NORMAL);
            //使用hutool当中自带的IdUtil工具类创建盐值
            String salt = IdUtil.simpleUUID().toUpperCase(Locale.ROOT);
            userVo.setSalt(salt);
            //然后使用shiro当中自带MD5加密，将创建的盐值加到密码当中去，迭代次数为两次
            userVo.setPwd(new Md5Hash(Constant.USER_DEFAULT_PWD, salt, 2).toString());
            sysUserService.save(userVo);
            return ResultObj.ADD_SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
            return ResultObj.ADD_ERROR;
        }
    }

    /**
     * 获取最大的排序码并且传给前端时进行加一操作
     *
     * @return
     */
    @RequestMapping("/loadUserMaxOrderNum")
    public Map<String, Object> loadUserMaxOrderNum() {
        HashMap<String, Object> map = new HashMap<>();
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("ordernum");
        List<SysUser> list = sysUserService.list(queryWrapper);
        if (list.size() > 0) {
            SysUser sysUser = list.get(0);
            map.put("value", sysUser.getOrdernum() + 1);
        } else {
            map.put("value", 1);
        }
        return map;
    }

    /**
     * 根据部门id获取用户
     *
     * @param deptid
     * @return
     */
    @RequestMapping("/loadUserByDeptId")
    public DataGridView loadUserByDeptId(Integer deptid) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(deptid != null, "deptid", deptid);
        queryWrapper.eq("available", Constant.AVAILABLE_TRUE);
        queryWrapper.eq("type", Constant.USER_TYPE_NORMAL);
        List<SysUser> sysUsers = sysUserService.list(queryWrapper);
        return new DataGridView(sysUsers);
    }

    /**
     * 自动获取用户名称的拼音然后传到前端进行渲染
     *
     * @param username
     * @return
     */
    @RequestMapping("/changeChineseToPinyin")
    public Map<String, Object> changeChineseToPinyin(String username) {

        Map<String, Object> map = new HashMap<>();
        String pingYin = PinyinUtils.getPingYin(username);
        if (username != null) {
            map.put("value", pingYin);
        } else {
            map.put("value", "");
        }
        return map;
    }

    /**
     * 根据直属领导的id找到他的信息，然后将这条信息传给前端
     * 值得注意的是，我们这里只传了一条给前端，当然，由于设定，我们查到的list集合当中也只会存一条数据
     * 但如果我们想要传多个领导信息给前端，那么我们前端就要学会用$.each(d,function(index,item){})去接收并进行赋值。当然这也只是猜想，具体实施还不清楚
     *
     * @param id
     * @return
     */
    @RequestMapping("/loadUserById")
    public DataGridView loadUserById(Integer id) {
        return new DataGridView(sysUserService.getById(id));
    }

    /**
     * 用户更新
     *
     * @param userVo
     * @return
     */
    @RequestMapping("/updateUser")
    public ResultObj updateUser(UserVo userVo) {
        try {
            sysUserService.updateById(userVo);
            return ResultObj.UPDATE_SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
            return ResultObj.UPDATE_ERROR;
        }
    }

    /**
     * 单独删除（部分实现，用户对应的角色未删除）
     *
     * @param id
     * @return
     */
    @RequestMapping("/deleteUserById")
    public ResultObj deleteUserById(Integer id) {
        try {
            sysUserService.removeById(id);
            return ResultObj.DELETE_SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
            return ResultObj.DELETE_ERROR;
        }
    }

    /**
     * 批量删除（部分实现，用户对应的角色未删除）
     *
     * @param userVo
     * @return
     */
    @RequestMapping("/batchDeleteUser")
    public ResultObj batchDeleteUser(UserVo userVo) {
        try {
            Integer[] ids = userVo.getIds();
            for (Integer id : ids) {
                sysUserService.removeById(id);
            }
            return ResultObj.DELETE_SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
            return ResultObj.DELETE_ERROR;
        }
    }

    /**
     * 重置密码
     *
     * @param id
     * @return
     */
    @RequestMapping("/resetPassword")
    public ResultObj resetPassword(Integer id) {
        try {
            UserVo userVo = new UserVo();
            userVo.setId(id);
            //使用hutool当中自带的IdUtil工具类创建盐值
            String salt = IdUtil.simpleUUID().toUpperCase(Locale.ROOT);
            userVo.setSalt(salt);
            //然后使用shiro当中自带MD5加密，将创建的盐值加到密码当中去，迭代次数为两次
            userVo.setPwd(new Md5Hash(Constant.USER_DEFAULT_PWD, salt, 2).toString());
            sysUserService.updateById(userVo);
            return ResultObj.RESET_SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
            return ResultObj.RESET_ERROR;
        }
    }

    /**
     * 分配角色——查询
     *
     * @param id
     * @return
     */
    @RequestMapping("/loadRoleByUid")
    public DataGridView loadRoleByUid(Integer id) {
        //首先，还是查询所有可以使用的角色，但是我们这里用于存储的方式变成了List<Map<String, Object>>，这样做的目的。
        //是为了方便我们后面添加一个属性字段传给前端时，不再需要去SysUser当中再添加一个属性字段了。
        QueryWrapper<SysRole> sysRoleQueryWrapper = new QueryWrapper<>();
        sysRoleQueryWrapper.eq("available", Constant.AVAILABLE_TRUE);
        List<Map<String, Object>> maps = sysRoleService.listMaps(sysRoleQueryWrapper);

        //根据前端传来的用户id找到对应的角色id集合
        List<Integer> rids = sysUserService.queryRoleUserByUid(id);

        //然后通过所有角色去和得到的角色id比较，有的加上LAY_CHECKED
        for (Map<String, Object> map : maps) {
            boolean LAY_CHECKED = false;
            for (Integer rid : rids) {
                Integer roleId = (Integer) map.get("id");
                if (roleId.equals(rid)) {
                    LAY_CHECKED = true;
                    //傻呀，用一个角色信息去和一群角色id比较，如果这个角色是被用户分配了的，那么肯定就要break退出，你不可能说重复比较吧。
                    break;
                }
            }
            map.put("LAY_CHECKED", LAY_CHECKED);
        }
        return new DataGridView((long) maps.size(), maps);
    }


    /**
     * 分配角色——保存
     *
     * @param userVo
     * @return
     */
    @RequestMapping("/saveRoleUser")
    public ResultObj saveRoleUser(UserVo userVo) {
        try {
            sysUserService.saveRoleUserByUid(userVo);
            return ResultObj.DISPATCH_SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
            return ResultObj.DISPATCH_ERROR;
        }

    }
}
